<template>
  <div class="homePageCss">
    <div id="mars3dContainer" class="mars3d-container"></div>
  </div>
</template>

<script setup>
import { ElMessage } from 'element-plus'
import * as mars3d from "mars3d";
import * as mars3dSpace from "mars3d-space";
import * as turf from '@turf/turf'
import 'mars3d/dist/mars3d.css';
import "mars3d-cesium/Build/Cesium/Widgets/widgets.css";
import {
  DeleteKey,
  Mark,
  Label,
  Change,
  BringToFrontOne,
  Asterisk,
  Rectangle,
  Editor,
  Export,
  ClearFormat,
  DatabaseForbid
} from "@icon-park/svg";

let map = null;
const initMars3d = (option) => {
  map = new mars3d.Map("mars3dContainer", option)
  // 针对不同终端的优化配置
  if (mars3d.Util.isPCBroswer()) {
    map.zoomFactor = 5.0; // 鼠标滚轮放大的步长参数

    // IE浏览器优化
    if (window.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
      map.viewer.targetFrameRate = 20; // 限制帧率
      map.scene.requestRenderMode = false; // 取消实时渲染
    }
  } else {
    map.zoomFactor = 5.0; // 鼠标滚轮放大的步长参数

    // 移动设备上禁掉以下几个选项，可以相对更加流畅
    map.scene.requestRenderMode = false; // 取消实时渲染
    map.scene.fog.enabled = false;
    map.scene.skyAtmosphere.show = false;
    map.scene.globe.showGroundAtmosphere = false;
  }

  // //二三维切换不用动画
  if (map.viewer.sceneModePicker) {
    map.viewer.sceneModePicker.viewModel.duration = 0.0;
  }

  // webgl渲染失败后，刷新页面
  map.on(mars3d.EventType.renderError, async () => {
    await $alert("程序内存消耗过大，请重启浏览器");
    window.location.reload();
  });

  map.on(mars3d.EventType.load, function (event) {
    map.addControl(toolButton)
    map.addControl(toolButton1)
    // addPoint()
    // addLine()
    // addIconPoint()
    // addModel()
    // addMovableMold()

    // 右键停止绘制
    map.on(mars3d.EventType.rightClick, function (event) {
      hasSelected.value = false
      map.graphicLayer.stopDraw()
    })

    // 键盘按下 Ctrl 键 调用角度测量
    // map.on(mars3d.EventType.keydown, function (event) {
    //   if (event.keyCode === 17 && event.ctrlKey) {
    //     removeGraphicLayerId('plannedRoutes')
    //     startMeasureAngle()
    //   }
    // })
  })

  emit("onload", map)
};

//  启动测量角度功能
// const startMeasureAngle = () => {
//   const tool = new mars3d.thing.Measure()
//   map.addThing(tool)
//   tool.angle().then(result => {
//     // console.log('🚀 ~ result -->', result)
//     tangentCoordinatesArr.value = result.points
//     // map.removeThing(tool)
//   })
// }

let hasSelected = ref(false)
const toolButton = new mars3d.control.ToolButton({
  title: "航线规划",
  icon: BringToFrontOne({ theme: "outline", fill: "#fff", size: "18" }),
  // className: ".tool_bookmark_btn",
  insertIndex: 5, // 插入的位置顺序, 1是home按钮后面
  click: () => {
    hasSelected.value = !hasSelected.value
    // console.log('🚀 ~ hasSelected.value -->', hasSelected.value)
    if (hasSelected.value) {
      paintTool()
      console.log("开始绘制")
    } else {
      // map.graphicLayer.endDraw()
      console.log("绘制结束~")
    }
  }
})

// 删除指定图层（id）
const removeGraphicLayerId = (id) => {
  const graphic = map.graphicLayer.getGraphicById(id)  // 获取指定图层
  // console.log('🚀 ~ graphic -->', graphic)
  map.graphicLayer.removeGraphic(graphic)  // 删除图层
};

// 删除指定图层（name）
const removeGraphicLayerName = (name) => {
  // console.log('🚀 ~ map.layers -->', map.graphicLayer.graphics)
  map.graphicLayer.graphics.forEach(item => {
    if (item.name === name) {
      // console.log('🚀 ~ item -->', item)
      map.graphicLayer.removeGraphic(item)
    }
  });
}

// 移除图层
const removeGraphic = (item) => {
  map.graphicLayer.removeGraphic(item.graphic)
}
// 隐藏图层
const hideGraphic = (item) => {
  item.graphic.show = false
}
// 显示图层
const showGraphic = (item) => {
  item.graphic.show = true
}

// 增加点
const addPoint = () => {
  const graphic = new mars3d.graphic.PointEntity({
    id: "123",
    position: [116.244399, 30.920459, 573.6], // 位置
    style: {
      color: "#ff0000", // 颜色
      pixelSize: 10, // 大小
      outlineColor: "#ffffff", // 外边框的颜色
      outlineWidth: 2, // 外边框的大小
      visibleDepth: false,  // 是否被遮挡
      label: {
        text: "demo点", // 注记，
        font_size: 18, // 文字的大小
        color: "#ffffff", // 文字的颜色
        pixelOffsetY: -10, // 文字的偏移量
        distanceDisplayCondition: true, // 是否按视距显示
        distanceDisplayCondition_far: 500000, // 最大距离
        distanceDisplayCondition_near: 0 // 最小距离
      }
    },
    // popup: "直接传参的popup",
  })
  map.graphicLayer.addGraphic(graphic)
}

// 增加图标点
function addIconPoint (positions, countNum) {
  removeGraphicLayerName('iconPoint')
  const graphic = new mars3d.graphic.BillboardEntity({
    id: 'iconPoint' + countNum,
    name: "iconPoint",
    position: positions,
    style: {
      image: "img/marker/mark-blue.png",
      scale: 1,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      clampToGround: false,
      visibleDepth: false,
    },
    attr: { remark: "示例3" }
  })
  map.graphicLayer.addGraphic(graphic)
}

// 增加线
const addLine = () => {
  const graphic = new mars3d.graphic.PolylineEntity({
    id: "789",
    positions: [
      [118.8, 32.06, 1000],
      [121.46, 31.23, 1000],
      [115.86, 28.69, 1000]
    ],
    style: {
      width: 5,
      color: "#3388ff",
      depthFail: false,  // 是否被遮挡
    },
    attr: { remark: "示例10" }
  })
  map.graphicLayer.addGraphic(graphic)
}

// 增加静止模型
const addModel = () => {
  const graphic = new mars3d.graphic.ModelEntity({
    id: "147",
    name: "静止模型",
    position: [116.308523, 30.942509, 1000],
    style: {
      url: "model/332.glb", // 模型地址按需更改
      scale: 1,
      minimumPixelSize: 20,
    },
    attr: { remark: "示例9" }
  })
  map.graphicLayer.addGraphic(graphic)
}

// 增加可移动模型
const addMovableMold = () => {
  const propertyFJ = getSampledPositionProperty([
    [116.341348, 30.875522, 1000],
    [116.341432, 30.871815, 1000],
    [116.347965, 30.866654, 1000],
    [116.352154, 30.855531, 1000],
    [116.341181, 30.85326, 1000],
    [116.334609, 30.856601, 1000],
    [116.337695, 30.866505, 1000],
    [116.345018, 30.870448, 1000],
    [116.345028, 30.870436, 1000]
  ])
  const graphicModel = new mars3d.graphic.ModelEntity({
    id: "369",
    position: propertyFJ,
    orientation: new Cesium.VelocityOrientationProperty(propertyFJ),
    style: {
      url: "model/332.glb",
      scale: 1,
      minimumPixelSize: 20,
    },
    path: {
      width: 2,
      leadTime: 0, // 不显示前方路线
      color: "#00ffff"
    },
    attr: { remark: "示例4" },
    hasEdit: false
  })
  map.graphicLayer.addGraphic(graphicModel)
  map.flyToGraphic(graphicModel)
}
const getSampledPositionProperty = (points) => {
  const property = new Cesium.SampledPositionProperty()
  property.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD

  const start = map.clock.currentTime
  const positions = mars3d.LngLatArray.toCartesians(points)
  for (let i = 0; i < positions.length; i++) {
    const time = Cesium.JulianDate.addSeconds(start, i * 20, new Cesium.JulianDate())
    const position = positions[i]
    property.addSample(time, position)
  }
  return property
}

// 绘制工具
const paintTool = () => {
  // 绘制的多边形点位
  let pointProcessing = []
  // 动态绘制闭合线段
  map.graphicLayer.startDraw({
    name: "drawClosedLineSegments",
    type: "polygon",
    style: {
      color: "#f6ef37",
      opacity: 0.3,
      clampToGround: true,  // 是否贴地
      outline: false,
      outlineWidth: 5,
      outlineColor: "#ffffff",
    },
    minPointNum: 3,
    success: function (graphic) {
      // console.log('🚀 ~ graphic -->', graphic)
      // console.log('🚀 ~ JSON.stringify(graphic.coordinates) -->', JSON.stringify(graphic.coordinates))
      pointProcessing = graphic.coordinates
      // console.log('🚀 ~ pointProcessing -->', pointProcessing)
      pointProcessing.forEach(element => {
        addDivPoint1(element, pointProcessing.indexOf(element) + 1)
      });
      emit('getPoint', graphic.coordinates)
      // emit('getPoint', graphic.points)
      hasSelected.value = false
    }
  })
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


let tangentCoordinatesArr = ref([])

const planRoutes = (polygonPositions, spacingMeter = 30, extendedDistance = 50, edgePointsIndices = [0, 1], courseDirection = false) => {
  // console.log('🚀 ~ polygonPositions -->', polygonPositions);

  if (polygonPositions.length === 0) {
    ElMessage.warning("当前未检测到测区，请先绘制测区！");
    return;
  }
  if (polygonPositions.length <= 3) {
    ElMessage.warning("绘制测区至少需要四个坐标点位！");
    return;
  }

  const hfDistance = spacingMeter; // 间隔距离，单位米
  // 航向方向，默认为逆向 true为forward 或 false为reverse
  const lineDirection = courseDirection ? 'forward' : 'reverse';

  // 将多边形位置转换为点数组
  let polyArr = polygonPositions;

  let polygonalCoordinatesArr = polygonPositions.map(([longitude, latitude, height]) => [parseFloat(longitude), parseFloat(latitude)]);
  const isClockwise1 = isCounterClockwise(polygonalCoordinatesArr);

  // 获取指定的边线
  const [startIndex, endIndex] = edgePointsIndices;
  let specifiedEdge = [];
  if (isClockwise1) {
    specifiedEdge = [polygonalCoordinatesArr[startIndex], polygonalCoordinatesArr[endIndex]];
  } else {
    specifiedEdge = [polygonalCoordinatesArr[startIndex], polygonalCoordinatesArr[endIndex]].reverse();
  }

  let polygon = turf.polygon([[...polygonalCoordinatesArr, polygonalCoordinatesArr[0]]]);

  // 计算分割数量
  const geodesic = Cesium.BoundingRectangle.fromPoints(polyArr.map(([lon, lat, alt]) => Cesium.Cartesian3.fromDegrees(lon, lat, alt)));
  const maxDimension = geodesic.width + geodesic.height;
  const len = Math.floor(maxDimension / hfDistance); // 计算分割数量

  let jdArrs = []; // 交点集合

  for (let i = 0; i <= len; i++) {
    // 生成与指定边线平行的分割线
    const offsetLine = turf.lineOffset(turf.lineString(specifiedEdge), i * hfDistance, { units: 'meters' });
    // 延长分割线以确保与多边形相交
    const extendedOffsetLine = extendLine(offsetLine, 10000); // 延长10000米
    // 计算分割线与多边形的交点
    const intersections = turf.lineIntersect(polygon, extendedOffsetLine);

    const coordinates = intersections.features.map(feature => feature.geometry.coordinates);

    // 对交点进行排序，确保从左到右或从上到下
    let sortedCoordinates = []
    if (i == 0) {
      sortedCoordinates = [polygonalCoordinatesArr[startIndex], polygonalCoordinatesArr[endIndex]].sort((a, b) => a[0] - b[0] || a[1] - b[1]);
    } else {
      sortedCoordinates = coordinates.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
    }

    // 构建弓字形路径
    for (let j = 0; j < sortedCoordinates.length; j += 2) {
      let start = sortedCoordinates[j];
      let end = sortedCoordinates[(j + 1) % sortedCoordinates.length];

      if (lineDirection === 'forward') {
        if (i % 2 !== 0) {
          [start, end] = [end, start];
        }
      } else if (lineDirection === 'reverse') {
        if (i % 2 === 0) {
          [start, end] = [end, start];
        }
      }
      // 确保 start 和 end 不是同一个点
      if (start !== end) {
        // 计算延长线（获取外扩坐标点）
        const extendedStart = turf.destination(turf.point(start), -extendedDistance, turf.bearing(turf.point(start), turf.point(end)), { units: 'meters' });
        const extendedEnd = turf.destination(turf.point(end), -extendedDistance, turf.bearing(turf.point(end), turf.point(start)), { units: 'meters' });

        jdArrs.push(extendedStart.geometry.coordinates, start, end, extendedEnd.geometry.coordinates);
      }
    }
  }
  // console.log('🚀 ~ jdArrs -->', jdArrs); // 打印最终交点集合
  if (jdArrs.length > 200) {
    ElMessage.warning("航飞区域点位数量不得超过200个，目前计算所得的点位为" + jdArrs.length + "个，请重新绘制回去后重新计算！");
  } else {
    createRouteLayer(jdArrs); // 创建航线图层
    jdArrs.forEach(element => {
      addDivPoint2(element, jdArrs.indexOf(element) + 1)
    });
  }
};

// const planRoutes = (polygonPositions, spacingMeter = 30, edgePointsIndices = [0, 1], courseDirection = false) => {
//   // console.log('🚀 ~ polygonPositions -->', polygonPositions)
//   // 检查多边形位置是否为空，如果为空则输出警告并返回
//     if (polygonPositions.length === 0) {
//       ElMessage.warning("当前未检测到测区，请先绘制测区！");
//       return;
//     }
//     if (polygonPositions.length <= 3) {
//       ElMessage.warning("绘制测区至少需要四个坐标点位！");
//       return;
//     }

//   const hfDistance = spacingMeter; // 间隔距离，单位米
//   // 航向方向，默认为逆向 true为forward 或 false为reverse
//   const lineDirection = courseDirection ? 'forward' : 'reverse';

//   let polyArr = polygonPositions.map(item => item._position); // 将多边形位置转换为点数组

//   // 将面拆分成线并转换为经纬度格式存储
//   const ellipsoid = Cesium.Ellipsoid.WGS84; // 使用WGS84椭球模型
//   const toLonLat = (cartesian) => {
//     const cartographic = ellipsoid.cartesianToCartographic(cartesian); // 将笛卡尔坐标转换为地理坐标
//     return [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]; // 转换为度数
//   };

//   // 将多边形顶点转换为经纬度
//   let polygonalCoordinatesArr = polygonPositions.map(item => toLonLat(item._position));
//   // console.log('🚀 ~ polygonalCoordinatesArr -->', polygonalCoordinatesArr)
//   const isClockwise1 = isCounterClockwise(polygonalCoordinatesArr)
//   // console.log('多边形顶点顺序:', isClockwise ? '顺时针' : '逆时针');

//   // 获取指定的边线
//   const [startIndex, endIndex] = edgePointsIndices;
//   let specifiedEdge = []
//   if (isClockwise1) {
//     specifiedEdge = [toLonLat(polyArr[startIndex]), toLonLat(polyArr[endIndex])];
//     // console.log('🚀 ~ specifiedEdge顺时针 -->', specifiedEdge)
//   } else {
//     specifiedEdge = [toLonLat(polyArr[startIndex]), toLonLat(polyArr[endIndex])].slice().reverse();
//     // console.log('🚀 ~ specifiedEdge逆时针 -->', specifiedEdge)
//   }
//   // console.log('🚀 ~ specifiedEdge -->', specifiedEdge)

//   let polygon = turf.polygon([[...polygonalCoordinatesArr, polygonalCoordinatesArr[0]]])

//   if (tangentCoordinatesArr.value.length != 0) {
//     const tangentCoordinatesList = tangentCoordinatesArr.value.map(item => toLonLat(item._position))
//     const tangentCoordinatesLine = turf.lineString(tangentCoordinatesList);
//     // console.log('🚀 ~ tangentCoordinatesLine -->', tangentCoordinatesLine)
//     // // 计算横线与多边形的交点
//     const tangentCoordinatesIntersections = turf.lineIntersect(polygon, tangentCoordinatesLine);
//     // console.log('🚀 ~ tangentCoordinatesIntersections -->', tangentCoordinatesIntersections)
//     // // 获取交点的坐标
//     const tangentCoordinatesIntersectionPoints = tangentCoordinatesIntersections.features.map(feature => feature.geometry.coordinates);
//     // console.log('🚀 ~ tangentCoordinatesIntersectionPoints -->', tangentCoordinatesIntersectionPoints)

//     if (tangentCoordinatesIntersectionPoints.length != 0) {
//       const intersectingEdges = getIntersectingEdges(polygonalCoordinatesArr, tangentCoordinatesIntersectionPoints);
//       // console.log('🚀 ~ intersectingEdges -->', intersectingEdges)
//       const newPolygonCoordinates = recombinePolygon(polygonalCoordinatesArr, intersectingEdges);
//       // console.log('🚀 ~ newPolygonCoordinates -->', newPolygonCoordinates)
//       for (let i = 0; i < newPolygonCoordinates.length; i++) {
//         addIconPoint(newPolygonCoordinates[i], i)
//       }
//       const isClockwise2 = isCounterClockwise(newPolygonCoordinates)
//       // console.log('🚀 ~ isClockwise2 -->', isClockwise2)
//       const [startIndex, endIndex] = edgePointsIndices;
//       if (isClockwise2) {
//         specifiedEdge = [toLonLat(polyArr[startIndex]), toLonLat(polyArr[endIndex])];
//         // console.log('🚀 ~ specifiedEdge顺时针 -->', specifiedEdge)
//       } else {
//         specifiedEdge = [toLonLat(polyArr[startIndex]), toLonLat(polyArr[endIndex])].slice().reverse();
//         // console.log('🚀 ~ specifiedEdge逆时针 -->', specifiedEdge)
//       }
//       polygon = turf.polygon([[...newPolygonCoordinates, newPolygonCoordinates[0]]])
//     }
//   }

//   //计算分割数量
//   const geodesic = Cesium.BoundingRectangle.fromPoints(polyArr); // 获取多边形的外接矩形
//   // console.log('🚀 ~ geodesic -->', geodesic)
//   const maxDimension = geodesic.width + geodesic.height;
//   const len = Math.floor(maxDimension / hfDistance); // 计算分割数量

//   let jdArrs = []; // 交点集合

//   for (let i = 0; i <= len; i++) {
//     // 生成与指定边线平行的分割线
//     const offsetLine = turf.lineOffset(turf.lineString(specifiedEdge), i * hfDistance, { units: 'meters' });
//     // 延长分割线以确保与多边形相交
//     const extendedOffsetLine = extendLine(offsetLine, 10000); // 延长10000米
//     // 计算分割线与多边形的交点
//     const intersections = turf.lineIntersect(polygon, extendedOffsetLine);


//     if (intersections.features.length > 0) {
//       if (lineDirection === 'forward') {
//         if (i % 2 === 0) {
//           intersections.features.forEach(feature => {
//             const coordinates = feature.geometry.coordinates;
//             jdArrs.push(coordinates);
//           });
//         } else {
//           intersections.features.reverse().forEach(feature => {
//             const coordinates = feature.geometry.coordinates;
//             jdArrs.push(coordinates);
//           });
//         }
//       } else if (lineDirection === 'reverse') {
//         if (i % 2 === 0) {
//           intersections.features.reverse().forEach(feature => {
//             const coordinates = feature.geometry.coordinates;
//             jdArrs.push(coordinates);
//           });
//         } else {
//           intersections.features.forEach(feature => {
//             const coordinates = feature.geometry.coordinates;
//             jdArrs.push(coordinates);
//           });
//         }
//       }
//     }
//   }

//   // console.log('🚀 ~ jdArrs -->', jdArrs); // 打印最终交点集合
//   if (jdArrs.length > 200) {
//     ElMessage.warning("航飞区域点位数量不得超过200个，目前计算所得的点位为" + jdArrs.length + "个，请重新绘制回去后重新计算！");
//   } else {
//     createRouteLayer(jdArrs); // 创建航线图层
//     jdArrs.forEach(element => {
//       addDivPoint2(element, jdArrs.indexOf(element) + 1)
//     });
//   }
// };

// 延长线段函数
const extendLine = (line, distance) => {
  const { coordinates } = line.geometry;
  const [start, end] = coordinates;
  const dx = end[0] - start[0];
  const dy = end[1] - start[1];
  const length = Math.sqrt(dx * dx + dy * dy);
  const unitX = dx / length;
  const unitY = dy / length;

  const extendedStart = [start[0] - unitX * distance, start[1] - unitY * distance];
  const extendedEnd = [end[0] + unitX * distance, end[1] + unitY * distance];

  return turf.lineString([extendedStart, extendedEnd]);
};

// const extendLine = (line, distance) => {
//   const [start, end] = line.geometry.coordinates;
//   const bearing = turf.bearing(turf.point(start), turf.point(end));

//   // 延长起点和终点
//   const extendedStart = turf.destination(turf.point(start), -distance, bearing, { units: 'meters' });
//   const extendedEnd = turf.destination(turf.point(end), distance, bearing, { units: 'meters' });

//   return turf.lineString([extendedStart.geometry.coordinates, extendedEnd.geometry.coordinates]);
// };

// 判断多边形顶点顺序
const isCounterClockwise = (points) => {
  let sum = 0;
  const n = points.length;
  for (let i = 0; i < n; i++) {
    const j = (i + 1) % n;
    sum += (points[j][0] - points[i][0]) * (points[j][1] + points[i][1]);
  }
  return sum > 0;
}

// 判断点是否在直线段上
const isPointOnLineSegment = (point, start, end) => {
  const x = point[0];
  const y = point[1];
  const x1 = start[0];
  const y1 = start[1];
  const x2 = end[0];
  const y2 = end[1];

  // 检查点是否在直线段的范围内
  if ((x1 <= x && x <= x2) || (x2 <= x && x <= x1)) {
    if ((y1 <= y && y <= y2) || (y2 <= y && y <= y1)) {
      // 检查点是否在直线上
      if (x1 !== x2) {
        const slope = (y2 - y1) / (x2 - x1);
        const intercept = y1 - slope * x1;
        return Math.abs(y - (slope * x + intercept)) < 1e-6;
      } else {
        return Math.abs(x - x1) < 1e-6;
      }
    }
  }
  return false;
};

// 找到交点对应的边
const getIntersectingEdges = (polygonCoordinates, intersectionPoints) => {
  const edges = [];
  for (let i = 0; i < polygonCoordinates.length - 1; i++) {
    const start = polygonCoordinates[i];
    const end = polygonCoordinates[i + 1];
    for (const point of intersectionPoints) {
      if (isPointOnLineSegment(point, start, end)) {
        edges.push({ start, end, point });
      }
    }
  }
  // 处理闭合多边形的最后一边
  const start = polygonCoordinates[polygonCoordinates.length - 1];
  const end = polygonCoordinates[0];
  for (const point of intersectionPoints) {
    if (isPointOnLineSegment(point, start, end)) {
      edges.push({ start, end, point });
    }
  }
  return edges;
};

// 重新组合多边形
const recombinePolygon = (polygonCoordinates, intersectingEdges) => {
  // console.log('🚀 ~ polygonCoordinates -->', polygonCoordinates);
  // console.log('🚀 ~ intersectingEdges -->', intersectingEdges);
  const newCoordinates = [];
  let currentIndex = 0;
  let foundIntersection = false;

  while (currentIndex < polygonCoordinates.length) {
    const currentPoint = polygonCoordinates[currentIndex];
    const nextPoint = polygonCoordinates[(currentIndex + 1) % polygonCoordinates.length];

    const edge = intersectingEdges.find(edge =>
      (edge.start[0] === currentPoint[0] && edge.start[1] === currentPoint[1]) &&
      (edge.end[0] === nextPoint[0] && edge.end[1] === nextPoint[1])
    );

    if (edge) {
      if (!foundIntersection) {
        // 如果还没有找到交点，先添加当前点
        newCoordinates.push(currentPoint);
      }
      // 添加交点
      newCoordinates.push(edge.point);
      foundIntersection = true;
    } else if (!foundIntersection) {
      // 只有在没有找到交点的情况下才添加当前点
      newCoordinates.push(currentPoint);
    }

    currentIndex++;
  }

  // 确保最后一个点被添加
  if (!foundIntersection && currentIndex < polygonCoordinates.length) {
    newCoordinates.push(polygonCoordinates[polygonCoordinates.length - 1]);
  }

  // console.log('🚀 ~ newCoordinates -->', newCoordinates);

  // 创建一个空数组来存储转换后的坐标
  let convertedPoints = [];

  // 遍历经纬度坐标数组并转换它们
  for (let i = 0; i < newCoordinates.length; i++) {
    const [lon, lat] = newCoordinates[i];
    const xyz = latLonToXYZ(lat, lon);
    const pointData = {
      _lng: lon,
      _lat: lat,
      _alt: 0, // 假设所有点的高度都是0
      _position: {
        Je: {
          x: xyz.x.toFixed(1),
          y: xyz.y.toFixed(1),
          z: xyz.z.toFixed(1)
        }
      }
    };

    convertedPoints.push(pointData);
  }
  emit('getPoint', convertedPoints)
  // console.log('🚀 ~ convertedPoints -->', convertedPoints)
  return newCoordinates;
};

// 定义一个函数来将经纬度坐标转换为 XYZ 坐标
function latLonToXYZ (lat, lon) {
  const RADIUS_EARTH = 6371000; // 地球平均半径，单位：米
  const radLat = lat * Math.PI / 180;
  const radLon = lon * Math.PI / 180;

  const x = RADIUS_EARTH * Math.cos(radLat) * Math.cos(radLon);
  const y = RADIUS_EARTH * Math.cos(radLat) * Math.sin(radLon);
  const z = RADIUS_EARTH * Math.sin(radLat);

  return { x, y, z };
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// 创建航线图层
const createRouteLayer = (effectiveRoute) => {
  const graphic1 = new mars3d.graphic.BillboardEntity({
    name: "贴地图标",
    id: 'uavStartPosition',
    position: effectiveRoute[0],
    style: {
      image: "img/marker/route-start.png",
      scale: 1,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      // clampToGround: true
    },
    attr: { remark: "开始位置" }
  })
  map.graphicLayer.addGraphic(graphic1)
  const graphic2 = new mars3d.graphic.BillboardEntity({
    name: "贴地图标",
    id: 'uavEndPosition',
    position: effectiveRoute[effectiveRoute.length - 1],
    style: {
      image: "img/marker/route-end.png",
      scale: 1,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      // clampToGround: true
    },
    attr: { remark: "结束位置" }
  })
  map.graphicLayer.addGraphic(graphic2)

  // 创建航线图层
  const graphic = new mars3d.graphic.PolylineEntity({
    id: 'plannedRoutes',
    positions: effectiveRoute,
    style: {
      width: 3,
      color: "#058ff5",
      clampToGround: true
    },
    attr: { remark: "规划航线" }
  });
  map.graphicLayer.addGraphic(graphic);

  createAnAircraftModel(effectiveRoute)
};

// 创建飞机模型 进行轨迹巡航
const createAnAircraftModel = (position) => {
  // console.log('🚀 ~ position -->', position)
  const graphic = new mars3d.graphic.FixedRoute({
    id: 'uavModel',
    speed: 50,
    name: "飞机",
    positions: position,
    clockLoop: false, // 是否循环播放
    model: {
      url: "model/332.glb",
      scale: 0.05,
      // heading: 360,  // 方向角 （度数值，0-360度）
      mergeOrientation: true,
      minimumPixelSize: 10
    },
  })
  map.graphicLayer.addGraphic(graphic)
  graphic.start()
}

const addDivPoint2 = (position, countNum) => {
  let src = "img/marker/linepoint.png"
  let title = String(countNum)
  const pointDivGraphic = new mars3d.graphic.DivGraphic({
    id: "divPoint2" + countNum,
    name: 'divPoint2',
    position: position,
    style: {
      html: `<div style="width: 28px;"><div style="float: left;width: 100%;"><img src="${src}" style="width: 28px;" /></div><div style="width: 28px;text-align:center;float: left;margin-top: -23px;">${title}</div></div>`,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM
    },
    hasEdit: true,
    hasEditContextMenu: false
  })
  map.graphicLayer.addGraphic(pointDivGraphic)
}
const addDivPoint1 = (position, countNum) => {
  let src = "img/marker/yellowPoint.png"
  let title = String(countNum)
  const pointDivGraphic = new mars3d.graphic.DivGraphic({
    id: "divPoint1" + countNum,
    name: 'divPoint1',
    position: position,
    style: {
      html: `<div style="width: 28px;"><div style="float: left;width: 100%;"><img src="${src}" style="width: 28px;" /></div><div style="width: 28px;text-align:center;float: left;margin-top: -23px;">${title}</div></div>`,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM
    },
    hasEdit: true,
    hasEditContextMenu: false
  })
  map.graphicLayer.addGraphic(pointDivGraphic)
}


//////////////////// 可视域分析 ////////////////////

// Thing对象
let sightline = new mars3d.thing.Sightline(
  {
    visibleColor: new Cesium.Color(0, 1, 0, 1), // 可视区域颜色
    hiddenColor: new Cesium.Color(1, 0, 0, 1), // 不可视区域颜色
  }
)

const toolButton1 = new mars3d.control.ToolButton({
  title: "可视域分析",
  icon: BringToFrontOne({ theme: "outline", fill: "#fff", size: "18" }),
  insertIndex: 6, // 插入的位置顺序, 1是home按钮后面
  click: () => {
    emit("toolClick1", true)
  }
})

// 定位到指定点
const positioning = (point, radius) => {
  const options = {
    radius: 1000  // 距离目标点的距离(单位：米)
  }
  removeGraphicLayer()
  addIconPoint(point, radius)
  addCircularLayer(point, radius)
  map.flyToPoint(point, options)
}

const pointCoordinates = ref([])

const mapSelectionCoordinates1 = (radius) => {
  let countNum = 0
  map.unbindContextMenu()
  map.setCursor("crosshair")
  map.onlyPickTerrainPosition = true  // 是否只拾取地形上的点，忽略模型和矢量数据
  map.on(mars3d.EventType.click, function (event) {
    map.setCursor("crosshair")
    const cartesian = event.cartesian
    const point = mars3d.LngLatPoint.fromCartesian(cartesian)
    point.format() // 经度、纬度、高度
    countNum++
    pointCoordinates.value = [point.lng, point.lat, point.alt]
    addIconPoint(pointCoordinates.value, countNum)
    addCircularLayer(pointCoordinates.value, radius)
    removeGraphicLayerName('polygonLayer')  // 移除之前的多边形
    sightline.clear()
    emit('coordinates-selected', pointCoordinates.value);
  })
  map.once(mars3d.EventType.rightClick, function (event) {
    countNum = 0
    map.setCursor("")
    map.off(mars3d.EventType.click)
    map.onlyPickTerrainPosition = false
  })
}

const viewshedAnalysis = (coordinatePoint, radius, numPoints) => {
  const circleCenter = coordinatePoint
  // 存储圆周上所有点的Cartesian3坐标
  let pointsOnCircle = [];
  for (let i = 0; i < numPoints; i++) {
    // 计算角度，从 2π 到 0 递减  正东方向
    const angle = 2 * Math.PI - (2 * Math.PI * i) / numPoints;
    // 计算纬度和经度
    const lat = circleCenter[1] + (radius / 111320) * Math.sin(angle);
    const lon = circleCenter[0] + (radius / (111320 * Math.cos(Cesium.Math.toRadians(circleCenter[1])))) * Math.cos(angle);
    // 创建坐标点
    const cartographic = [lon, lat, circleCenter[2]];
    // 添加到 pointsOnCircle 数组
    pointsOnCircle.push(cartographic);
    // console.log('🚀 ~ pointsOnCircle -->', pointsOnCircle)
  }
  // 执行通视分析
  performLineOfSightAnalysis(circleCenter, pointsOnCircle, numPoints);
}

// 圆形图层
const addCircularLayer = (position, radius) => {
  removeGraphicLayerId('circularLayer')
  const pointLight = new mars3d.graphic.CircleEntity({
    position: position,
    id: 'circularLayer',
    style: {
      radius: radius,
      color: "#ffffff",
      opacity: 0.5,
      // clampToGround: true,
      // heightReference: Cesium.HeightReference.NONE,
    },
  })
  map.graphicLayer.addGraphic(pointLight)
}

// 多边形图层
const addPolygonLayer = (position, numPoints, color, whetherToCalculateArea) => {
  // removeGraphicLayerName('polygonLayer')
  const positionArr = position
  // 计算面积
  let area = 0
  if (whetherToCalculateArea) {
    // if (position.length == numPoints) {
    positionArr.push(positionArr[0])
    const polygon = turf.polygon([positionArr])
    area = parseFloat(turf.area(polygon).toFixed(2))  // 单位为平方米
    // console.log('🚀 ~ 面积area -->', area)
    // }
  }

  const graphic = new mars3d.graphic.PolygonEntity({
    positions: position,
    name: "polygonLayer",
    style: {
      color: color,
      opacity: 0.5,
      label: {
        text: `面积约：${area.toFixed(2)}平方米`,
        fontSize: 18,
        color: "#ffffff",
        visibleDepth: false,
        pixelOffsetY: -10,
      }
    },
  })
  if (!whetherToCalculateArea) {
    delete graphic.style.label
  }
  map.graphicLayer.addGraphic(graphic)
  // console.log('🚀 ~ graphic.style -->', graphic.style)
}

// 修改半径重新绘制圆形
const redrawTheCircle = (radius) => {
  addIconPoint(pointCoordinates.value, radius)
  addCircularLayer(pointCoordinates.value, radius)
  removeGraphicLayerName('polygonLayer')  // 移除之前的多边形
  sightline.clear()
}

// 计算可视域分析
const performLineOfSightAnalysis = async (observerPosition, targetPosition, numPoints) => {
  // console.log('🚀 ~ map.graphicLayer.getGraphicById("circularLayer") -->', map.graphicLayer.getGraphicById("circularLayer"))
  if (map.graphicLayer.getGraphicById("circularLayer") == undefined) {
    ElMessage.warning('请先确定区域后再进行分析！')
    return
  }

  if (sightline.isAdded == false) {
    map.addThing(sightline)
  } else {
    removeGraphicLayerName('polygonLayer')  //移除之前的多边形
    // sightline.clear()
  }

  map.setCursor("")
  map.off(mars3d.EventType.click)
  map.onlyPickTerrainPosition = false

  let visualAreaCollection = []
  let invisibleAreaCollection = []

  const startPoint = Cesium.Cartographic.toCartesian(Cesium.Cartographic.fromDegrees(observerPosition[0], observerPosition[1], observerPosition[2]));

  // 使用 new Promise 实现延时1秒
  await new Promise(resolve => setTimeout(resolve, 1000));

  const promises = targetPosition.map((item, index) => {
    const endPoint = Cesium.Cartographic.toCartesian(Cesium.Cartographic.fromDegrees(item[0], item[1], item[2]));
    map.scene.globe.depthTestAgainstTerrain = true;
    const results = sightline.add(startPoint, endPoint);
    if (results.position) {
      const cartographic = Cesium.Cartographic.fromCartesian(results.position);
      const longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6);
      const latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6);
      const heightString = observerPosition[2];
      const point = [+longitudeString, +latitudeString, +heightString];
      visualAreaCollection.push(point);
    } else {
      visualAreaCollection.push(item);
    }
  });

  await Promise.all(promises);

  const fullAreaPolygon = turf.polygon([[...targetPosition, targetPosition[0]]]); // 替换为实际坐标
  const visibleAreaPolygon = turf.polygon([[...visualAreaCollection, visualAreaCollection[0]]]); // 替换为实际坐标

  // 执行差集操作
  // console.log('🚀 ~ turf.difference(fullAreaPolygon, visibleAreaPolygon) -->', turf.difference(fullAreaPolygon, visibleAreaPolygon))
  if (turf.difference(fullAreaPolygon, visibleAreaPolygon)) {
    invisibleAreaCollection = turf.difference(fullAreaPolygon, visibleAreaPolygon).geometry.coordinates[0];
    invisibleAreaCollection.forEach((item) => {
      item.push(observerPosition[2])
    })
    addPolygonLayer(visualAreaCollection, numPoints, new Cesium.Color(0, 1, 0, 1), true); // 可见区域
    addPolygonLayer(invisibleAreaCollection, numPoints, new Cesium.Color(1, 0, 0, 1), false); // 不可见区域
  } else {
    addPolygonLayer(visualAreaCollection, numPoints, new Cesium.Color(0, 1, 0, 1), true); // 可见区域
  }
  // invisibleAreaCollection = turf.difference(fullAreaPolygon, visibleAreaPolygon).geometry.coordinates[0];
  // console.log('🚀 ~ invisibleAreaCollection -->', invisibleAreaCollection)
  // invisibleAreaCollection.forEach((item) => {
  //   item.push(observerPosition[2])
  // })
  // addPolygonLayer(visualAreaCollection, numPoints, new Cesium.Color(0, 1, 0, 1)); // 可见区域
  // addPolygonLayer(invisibleAreaCollection, numPoints, new Cesium.Color(1, 0, 0, 1)); // 不可见区域
  map.scene.globe.depthTestAgainstTerrain = false;
  sightline.clear()

  // sightline.on(mars3d.EventType.start, function (event) {
  //   console.log('开始分析', event)
  // })
  // sightline.on(mars3d.EventType.end, function (event) {
  //   console.log('分析完成', event)
  // })
}

// 移除用于可视域分析的图层
const removeGraphicLayer = () => {
  removeGraphicLayerName('iconPoint')  // 移除之前的选点
  removeGraphicLayerId('circularLayer')  // 移除之前的圆
  removeGraphicLayerName('polygonLayer')  // 移除之前的多边形
  sightline.clear()  // 移除之前的可视域分析
}


const emit = defineEmits(["onload", "getPoint", "toolClick1", "coordinates-selected"])
defineExpose({
  removeGraphicLayerId,
  removeGraphicLayerName,
  paintTool,
  planRoutes,
  positioning,
  mapSelectionCoordinates1,
  redrawTheCircle,
  viewshedAnalysis,
  removeGraphicLayer
});

onMounted(() => {
  // 获取配置
  mars3d.Util.fetchJson({ url: 'public/config/config.json' }).then((data) => {
    // console.log('🚀 ~ data -->', data)
    if (data.map3d) {
      initMars3d(data.map3d)
    } else {
      initMars3d(data)
    }
  })
});

// 组件卸载之前销毁mars3d实例
onBeforeUnmount(() => {
  if (map) {
    map.destroy()
    map = null
  }
})

</script>

<style lang="scss">
/**cesium 工具按钮栏*/
.cesium-viewer-toolbar {
  top: auto !important;
  bottom: 35px !important;
  // left: 12px !important;
  right: 12px !important;

  .cesium-svgPath-svg {
    width: 28px !important;
    height: 28px !important;
  }

  svg {
    width: 24px !important;
    height: 24px !important;
  }
}

.cesium-toolbar-button img {
  height: 100%;
}

.cesium-viewer-toolbar>.cesium-toolbar-button,
.cesium-navigationHelpButton-wrapper,
.cesium-viewer-geocoderContainer {
  margin-bottom: 5px;
  float: left;
  clear: both;
  text-align: center;
}

.cesium-button {
  background-color: rgba(23, 49, 71, 0.7);
  color: #e6e6e6;
  fill: #e6e6e6;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  line-height: 42px;
}

.cesium-button:hover {
  background-color: rgba(0, 138, 255, 0.7);
}

/**cesium 底图切换面板*/
.cesium-baseLayerPicker-dropDown {
  bottom: 0;
  left: 40px;
  max-height: 700px;
  margin-bottom: 5px;
  background-color: rgba(23, 49, 71, 0.7);
}

/**cesium 帮助面板*/
.cesium-navigation-help {
  top: auto;
  bottom: 0;
  left: 40px;
  transform-origin: left bottom;
  background: none;
  background-color: rgba(23, 49, 71, 0.8);

  .cesium-navigation-help-instructions {
    background: none;
  }

  .cesium-navigation-button {
    background: none;
  }

  .cesium-navigation-button-selected,
  .cesium-navigation-button-unselected:hover {
    background-color: rgba(23, 49, 71, 1);
  }
}

/**cesium 二维三维切换*/
.cesium-sceneModePicker-wrapper {
  width: auto;
}

.cesium-sceneModePicker-wrapper .cesium-sceneModePicker-dropDown-icon {
  float: right;
  margin: 0 3px;
}

/**cesium 底图切换*/
.cesium-baseLayerPicker-dropDown {
  bottom: 0;
  right: 55px !important;
  left: auto;
  max-height: 700px;
  margin-bottom: 5px;
  background-color: rgba(23, 49, 71, 0.7);
}

/**cesium POI查询输入框*/
.cesium-viewer-geocoderContainer .search-results {
  left: 0;
  right: 40px;
  width: auto;
  z-index: 9999;
}

.cesium-geocoder-searchButton {
  background-color: rgba(23, 49, 71, 0.8);
}

.cesium-viewer-geocoderContainer .cesium-geocoder-input {
  background-color: rgba(63, 72, 84, 0.7);
}

.cesium-viewer-geocoderContainer .cesium-geocoder-input:focus {
  background-color: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}

.cesium-viewer-geocoderContainer .search-results {
  background-color: rgba(23, 49, 71, 0.8);
}

/**cesium info信息框*/
.cesium-infoBox {
  top: 50px;
  background: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}

.cesium-infoBox-title {
  background-color: rgba(23, 49, 71, 0.8);
}

/**cesium 任务栏的FPS信息*/
.cesium-performanceDisplay-defaultContainer {
  top: auto;
  bottom: 35px;
  right: 50px;
}

.cesium-performanceDisplay-ms,
.cesium-performanceDisplay-fps {
  color: #fff;
}

/**cesium tileset调试信息面板*/
.cesium-viewer-cesiumInspectorContainer {
  top: 10px;
  left: 10px;
  right: auto;
}
</style>
